#include "formulafactory.h"

Formula* FormulaFactory::createNewFormula(unsigned int& size, bool isComplex) {
    Formula *myFormula = new Formula();
    LinkedList<FormulaElement>& myFormulaElements=myFormula->getListOfFormulaElements();
    assert(myFormulaElements.getSize()==0);
    if(isComplex)
        FormulaFactory::createComplexFormula(myFormulaElements, size);
    else
        FormulaFactory::createRealFormula(myFormulaElements, size);

    return myFormula;
}

void FormulaFactory::createComplexFormula(LinkedList<FormulaElement>& myFE, unsigned int& size) {
}

void FormulaFactory::createRealFormula(LinkedList<FormulaElement>& myFE, unsigned int& size) {
    unsigned int level=0;
    if(size<3)
        return; // no formula possible
    assert(size%2);
    unsigned int maxAmountOfRemainingNumbers = (size+1)/2-2;
    // add first two numbers. First two elements must be numbers.
    myFE.addAtStart(FormulaFactoryUtil::getRandomRealNumberOrVariable()); // (0 bis und mit 63) minus 31
	myFE.addAtStart(FormulaFactoryUtil::getRandomRealNumberOrVariable()); // (0 bis und mit 63) minus 31
    level+=2;
    while(maxAmountOfRemainingNumbers>0 || level!=1) {
        switch(rand()>>27){		// 0 bis und mit 15
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
                if(maxAmountOfRemainingNumbers > 0) {
                    myFE.addAtEnd(FormulaFactoryUtil::getRandomRealNumberOrVariable()); // (0 bis und mit 63) minus 31
                    ++level;
                    --maxAmountOfRemainingNumbers;
                }
                else {
                    assert(level>1);
                    myFE.addAtEnd(FormulaFactoryUtil::getRandomRealOperation());
					--level;
                }
				break;
			case 9:
			case 10:
			case 11:
			case 12:
			case 13:
			case 14:
			case 15:
				if(level>1){
					myFE.addAtEnd(FormulaFactoryUtil::getRandomRealOperation());
					--level;
				}
				else {
                    assert(maxAmountOfRemainingNumbers > 0);
                        myFE.addAtEnd(FormulaFactoryUtil::getRandomRealNumberOrVariable()); // (0 bis und mit 63) minus 31
                        ++level;
                        --maxAmountOfRemainingNumbers;
				}
                break;
            default:
                assert(false);
        }
    }
}

Formula* FormulaFactory::simpleRecombination(Formula& formula1, Formula& formula2) {
    Formula* returnFormula = new Formula();
    assert(returnFormula->getListOfFormulaElements().getSize()==0);
    FormulaFactory::copyFirstFormulaToTheEndOfTheSecond(formula1, *returnFormula);
    FormulaFactory::copyFirstFormulaToTheEndOfTheSecond(formula2, *returnFormula);
    returnFormula->getListOfFormulaElements().addAtEnd(*(new RealPlus()));
    double tempDouble = 0.5;
    returnFormula->getListOfFormulaElements().addAtEnd(*(new RealNumber(tempDouble)));
    returnFormula->getListOfFormulaElements().addAtEnd(*(new RealMultiplication()));
    return returnFormula;
}
